
#include <cstdio>
#include <iostream>
#include <cstring>
#include <fstream>
#include <sstream>
#include "library2.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))



template <class T>
class DynamicArray{
public:
	T** array;
	int size;
public:
	int current;

	DynamicArray(int N):
		array(new T*[N]), size(N), current(0){
			for(int i=0; i<N; i++){
				array[i]=NULL;
			}
		}

	~DynamicArray(){

		delete[] array;
	}
	int insert(T* ptr){
		if(current<size){
					array[current]=ptr;
					return current++;
		}
		T** newArray = new T*[2*size];
		for(int i =0; i<size; i++){
			newArray[i]=array[i];
			newArray[i+size]=NULL;
		}
		delete[] array;
		newArray[current]=ptr;
		array=newArray;
		size=2*size;
		return current++;
		}

	void edit(int i, T* ptr){
		if(i>=current){
			return;
		}
		array[i]=ptr;
	}


		T* operator[](int i) {
		if(i<size){
					return array[i];
			}
		return NULL;
		}
};


//*********************Errors*******************************

//************************Tower*********************************

//************************Cube*********************************
typedef struct Cube{
	int _width;
	int _length;
	int _parent;
	int _position;
	int _tower;
	int _relativeHight;
};

class Tower{
private:
public:
	int _size;
	Cube* _base;
	Cube* _top;
	Cube* _root;

public:
	Tower(Cube* cube):
		_size(1), _base(cube), _top(cube), _root(cube){}
	Tower(int size, Cube* base,Cube* top,Cube* root):
		_size(size),_base(base),_top(top),_root(root){}
};

class Lego{

protected:
	DynamicArray <Cube> _pieces;
	DynamicArray <Tower> _towers;
	int find(int N, int* height) {
		if(!_pieces[N]){
			return -1;
		}
		if(_pieces[N]->_parent==-1){
			if(height!=NULL) *height=_pieces[N]->_relativeHight;
				return _pieces[N]->_tower;
		}
		if(_pieces[_pieces[N]->_parent]->_parent!=-1){
			Cube* cube=_pieces[N];
			int sum=0;
			while(cube->_parent!=-1){
				sum+=cube->_relativeHight;
				cube=_pieces[cube->_parent];
			}
			Cube* root=cube;
			cube=_pieces[N];
			Cube* next=_pieces[cube->_parent];
			while(next->_parent!=-1){
				sum-=cube->_relativeHight;
				cube->_relativeHight+=sum;
				cube->_parent=root->_position;
				cube=next;
				next=_pieces[next->_parent];
			}
		}
			if(height!=NULL)*height=_pieces[N]->_relativeHight + _pieces[_pieces[N]->_parent]->_relativeHight;
			return _pieces[_pieces[N]->_parent]->_tower;
	}
public:
	Lego(): _pieces(300), _towers(300){}
	virtual ~Lego(){
		for(int i=0; i<_towers.current; i++){
			delete _towers[i];
		}
		for(int i=0; i<_pieces.current; i++){
			delete _pieces[i];
		}

	}

		virtual StatusType addCube(int length, int width){
			if(length<1 || width<1) return INVALID_INPUT;
			Cube temp = {width, length, -1, -1, -1, 0};
			Cube* newCube=new Cube;
			*newCube= temp;
			Tower* newTower=new Tower(newCube);
			newCube->_tower=_towers.insert(newTower);
			newCube->_position = _pieces.insert(newCube);
			return SUCCESS;

	}
	virtual StatusType putOnTop(int cubeUp,int cubeDown){
		if(cubeUp<0 || cubeDown<0){
			return INVALID_INPUT;
		}
		int towerUp = find(cubeUp,NULL);
		int towerDown = find(cubeDown,NULL);
		if(towerUp==-1 || towerDown==-1 || towerDown==towerUp){
			return FAILURE;
		}
		int downLength = _towers[towerDown]->_top->_length;
		int downWidth = _towers[towerDown]->_top->_width;
		int upWidth = _towers[towerUp]->_base->_width;
		int upLength = _towers[towerUp]->_base->_length;
		if( ! ((upLength<= downWidth && upWidth<=downLength)
				||((upLength<=downLength && upWidth<=downWidth))) ){
			return FAILURE;
		}
		if(cubeUp == 190  && cubeDown == 3){
			int nothingTOdo;
			nothingTOdo = 0;
		}
		int toDeleteTower;
		if(_towers[towerDown]->_size < _towers[towerUp]->_size){
			_towers[towerUp]->_root->_relativeHight += _towers[towerDown]->_size;
			_towers[towerDown]->_root->_relativeHight -= _towers[towerUp]->_root->_relativeHight;
			_towers[towerDown]->_root->_parent=_towers[towerUp]->_root->_position;
			_towers[towerUp]->_size += _towers[towerDown]->_size;
			_towers[towerUp]->_base = _towers[towerDown]->_base;
			_towers[towerDown]->_root->_tower=-1;
			toDeleteTower = towerDown;
		}else{
			_towers[towerUp]->_root->_relativeHight += _towers[towerDown]->_size;
			_towers[towerUp]->_root->_relativeHight -= _towers[towerDown]->_root->_relativeHight;
			_towers[towerUp]->_root->_parent=_towers[towerDown]->_root->_position;
			_towers[towerDown]->_size += _towers[towerUp]->_size;
			_towers[towerDown]->_top = _towers[towerUp]->_top;
			_towers[towerUp]->_root->_tower=-1;
			toDeleteTower = towerUp;
		}
		delete _towers[toDeleteTower];
		_towers.current--;
		if(toDeleteTower==_towers.current){
			_towers.edit(_towers.current,NULL);
			return	SUCCESS;
		}
		_towers.edit(toDeleteTower,_towers[_towers.current]);
		_towers.edit(_towers.current,NULL);
		_towers[toDeleteTower]->_root->_tower=toDeleteTower;
		return SUCCESS;
	}

	StatusType towerHeight(int cube, int* height){
		if(cube<0 || height==NULL) return INVALID_INPUT;
		int tower=find(cube,NULL);
		if(tower==-1) return FAILURE;
		*height=_towers[tower]->_size;
		return SUCCESS;
	}
	StatusType HeightFromGround(int cube, int* height){
		if(cube<0 || height==NULL) return INVALID_INPUT;
		if(_pieces[cube]==NULL) return FAILURE;
		find(cube,height);
		return SUCCESS;
	}
	virtual StatusType TowersOfHeightBetween(int min, int max, int* num){
		if(min<0 ||  max<0 || min>max || num==NULL) return INVALID_INPUT;
		return FAILURE;
	}



};

typedef enum{LEFT,
	RIGHT,
	UNDEFINED
} POSITION;

class compareTowers{
public:
	int operator()(const Tower* t1 ,const Tower* t2) const{
		if(t1->_size==t2->_size){
		return (t1->_root->_tower-t2->_root->_tower);
		}
		return (t1->_size-t2->_size);
	}
};

class Vertex{
public:
//	data members
		Tower* data;
		Vertex* parent;
		int leftHight;
		int rightHight;
		int children;
		Vertex* left;
		Vertex* right;
//		c'tors
		Vertex(Tower* tower, Vertex* parent,int Lhight=0, int Rhight=0, int Children=1,
				Vertex* left=NULL, Vertex* right=NULL):
			 data(tower),parent(parent), leftHight(Lhight), rightHight(Rhight),children(Children),
			 left(left), right(right)  {}
		Vertex(const Vertex& v):
			data(v.data),parent(v.parent), leftHight(v.leftHight),
			rightHight(v.rightHight), children(v.children), left(v.left), right(v.right){}

		inline void updateHights(){
			if(this==NULL) return;
			if(left!=NULL) leftHight=1+MAX(left->leftHight, left->rightHight);
			else leftHight=0;
			if(right!=NULL) rightHight=1+MAX(right->leftHight, right->rightHight);
			else rightHight=0;
		}

};

class CompareOneTower{
	int _height;
	int _position;
public:
	CompareOneTower(int h, int pos):
		_height(h), _position(pos){}
	int operator()(Tower* t) const{
		if(t->_size==_height){
			return (t->_root->_tower-_position);
			}
			return (t->_size-_height);
	}
};

template <class Compare>
class AVL_Tree{
	private:
		Vertex* root;
		Compare compare;

		//******************Help Functions********************************//
		void LL(Vertex& B, Vertex& A){

				if(&B!=root){
					if(B.parent->left==&B){
						B.parent->left=&A;
					}
					else{
						B.parent->right=&A;
					}
				A.parent=B.parent;
				}
				else{
					root=&A;
					A.parent=NULL;
				}
				Vertex* tempAR=A.right;

				A.right=&B;
				B.parent=&A;

				B.left=tempAR;
				if(tempAR!=NULL){
					tempAR->parent=&B;
					 // update the sub-trees hights
					B.leftHight=1+MAX(B.left->leftHight , B.left->rightHight);
					B.children=B.children-A.children+tempAR->children;
					A.children=A.children-tempAR->children+B.children;
				}
				else {	B.leftHight=0;
						B.children-=A.children;
						A.children+=B.children;
				}
				A.rightHight=1+MAX(B.leftHight , B.rightHight);
			}

			void LR(Vertex& C, Vertex& B, Vertex& A){
				if(&C!=root){
							if(C.parent->left==&C){
								C.parent->left=&B;
							}
							else{
								C.parent->right=&B;
							}
						B.parent=C.parent;
					}
				else{
					root=&B;
					B.parent=NULL;
				}
				Vertex* tempBR=B.right;
				Vertex* tempBL=B.left;

				B.right=&C;
				C.parent=&B;

				B.left=&A;
				A.parent=&B;
				A.right=tempBL;
				C.left=tempBR;
				if(tempBR!=NULL){
					tempBR->parent=&C;
					C.leftHight=1+MAX(C.left->rightHight, C.left->leftHight);
					C.children=C.children-A.children+tempBR->children;
				}
				else{
					C.leftHight=0;
					C.children=C.children-A.children;
				}
				if(tempBL!=NULL){
					tempBL->parent=&A;
					A.rightHight=1+MAX(A.right->rightHight, A.right->leftHight);
					A.children=A.children-B.children+tempBL->children;
				}
				else {
					A.rightHight=0;
					A.children=A.children-B.children;
				}
				B.rightHight=1+MAX(B.right->rightHight, B.right->leftHight);
				B.leftHight=1+MAX(B.left->rightHight, B.left->leftHight);
				B.children=C.children+A.children+1;
			}

			void RR(Vertex& B, Vertex& A){
				if(&B!=root){
							if(B.parent->left==&B){
								B.parent->left=&A;
							}
							else{
								B.parent->right=&A;
							}
						A.parent=B.parent;
					}
						else {
							root=&A;
							A.parent=NULL;
						}
						Vertex* tempAL=A.left;
						A.left=&B;
						B.parent=&A;
						B.right=tempAL;
						if(tempAL!=NULL){
							tempAL->parent=&B;
							B.rightHight=1+MAX(B.right->leftHight , B.right->rightHight);
							B.children=B.children-A.children+tempAL->children;
							A.children=A.children-tempAL->children+B.children;
						}
						else{
							B.rightHight=0;
							B.children-=A.children;
							A.children+=B.children;
						}
						A.leftHight=1+MAX(B.leftHight , B.rightHight);
			}
			void RL(Vertex& C, Vertex& B, Vertex& A){
				if(&C!=root){
							if(C.parent->left==&C){
								C.parent->left=&B;
							}
							else{
								C.parent->right=&B;
							}
						B.parent=C.parent;
				}
				else{
					root=&B;
					B.parent=NULL;
				}
				Vertex* tempBR=B.right;
				Vertex* tempBL=B.left;

				B.left=&C;
				C.parent=&B;
				B.right=&A;
				A.parent=&B;
				A.left=tempBR;

				C.right=tempBL;
				if(tempBL!=NULL){
					tempBL->parent=&C;
					C.rightHight=1+MAX(C.right->rightHight, C.right->leftHight);
					C.children=C.children-A.children+tempBL->children;
				}
				else{
					C.rightHight=0;
					C.children-=A.children;
				}
				if(tempBR!=NULL){
					tempBR->parent=&A;
					A.leftHight=1+MAX(A.left->rightHight, A.left->leftHight);
					A.children=A.children-B.children+tempBR->children;
				}
				else{
					A.leftHight=0;
					A.children-=B.children;
				}
				B.rightHight=1+MAX(B.right->rightHight, B.right->leftHight);
				B.leftHight=1+MAX(B.left->rightHight, B.left->leftHight);
				B.children=A.children+C.children+1;
			}
			int getParentPosition(Vertex* v){
				if(v->parent->left!=NULL && v->parent->left==v)
					return LEFT;
				return RIGHT;
			}


			void fixBfRemove(Vertex* v){ // make all the roles in a path from v to root.
				if(v==NULL){return;}
				if(v->left!=NULL) v=v->left;
				else if(v->right!=NULL) v=v->right;
				while(v!=root){
									v->updateHights();
									Vertex* p=v->parent;
									p->updateHights();
									if(p->leftHight-p->rightHight == -2){
										if(p->right->leftHight-p->right->rightHight==-1 || p->right->leftHight-p->right->rightHight==0){
											RR(*p,*(p->right));
										}
										else{
											RL(*p,*(p->right->left),*(p->right));
											v=p;
											}
									}
									else if(p->leftHight-p->rightHight == 2){
										if(p->left->leftHight-p->left->rightHight==-1){
											LR(*p,*(p->left->right),*(p->left));
											v=v->parent;
										}else LL(*p,*(p->left));
									}
									v=p;
								}
								while(v!=NULL){
									v->updateHights();
									v=v->parent;
								}
			}
			void fixBF(Vertex* v){
				int lastSteps[2]={UNDEFINED,UNDEFINED };
				while(v!=root){
					Vertex* p=v->parent;
					if( MAX(p->leftHight, p->rightHight)>= 1+ MAX(v->leftHight, v->rightHight) ){
						break;        // to update?
					}
					p->updateHights();
					lastSteps[0]=getParentPosition(v);
					if(p->leftHight-p->rightHight == -2){
						if(lastSteps[1]==RIGHT){
							RR(*p,*v);
						}
						else{
							RL(*p,*(v->left),*v);
							v=p;
							}
						break;
					}
					if(p->leftHight-p->rightHight == 2){
						if(lastSteps[1]==RIGHT){
							LR(*p,*(v->right),*v);
							v=v->parent;
						}else LL(*p,*v);
						break;
					}
					lastSteps[1]=lastSteps[0];
					v=p;
				}
				while(v!=NULL){
					v->updateHights();
					v=v->parent;
				}
			}
			POSITION deleteLeaf(Vertex& v){
				POSITION result;
				if(&v==root)  result=UNDEFINED;
				else if(v.parent->left==&v)result=LEFT;
				else result=RIGHT;
				Vertex* p=v.parent;
				if(result==LEFT) p->left=NULL;
				else if(result==RIGHT) p->right=NULL;
				else root = NULL;
				Vertex* parent=v.parent;
				while(parent!=NULL){
					parent->children--;
					parent=parent->parent;
				}
				delete &v;
				return result;
			}

			void deleteParentToOne(Vertex& p){

				if(p.left!=NULL){
					p.data=p.left->data;
					deleteLeaf(*p.left);
					}
				else{
					p.data=p.right->data;
					deleteLeaf(*p.right);
				}
		}




			/**************************/
	public:
		AVL_Tree():root(NULL),compare(Compare()){}
		~AVL_Tree(){
			postOrderDelete(root);
		}

		void postOrderDelete(Vertex* v){
			if(v!=NULL){
				postOrderDelete(v->left);
				postOrderDelete(v->right);
				delete v;
				v = NULL;
			}
			return;
		}
												// add a new vertex in the tree
		bool addVertex(Tower* tower){
			if(!root){
				root=new Vertex(tower, NULL);
				return true;
			}
			Vertex* currVertex=root;
			Vertex* parent;
			bool leftOrRight;
			int diff;
			while(currVertex){
				diff=compare(currVertex->data, tower);
				if(diff==0){ return false;}
				else if(diff<0){
					parent=currVertex;
					currVertex=currVertex->right;
					leftOrRight = false;
				}
				else{
					parent=currVertex;
					currVertex=currVertex->left;
					leftOrRight = true;
				}
			}
			currVertex=new Vertex(tower, parent);
			currVertex->parent=parent;
			if(leftOrRight){
				parent->left = currVertex;
			}
			else{
				parent->right=currVertex;
			}
			do{
			parent->children++;    // fix children num
			parent=parent->parent;
			}while (parent!=NULL);

			fixBF(currVertex);
			return true;
		}
		Vertex* findNext(Vertex* v){
			Vertex* result;
			result=v->right;
			while(result->left!=NULL){
				result=result->left;
			}
			return result;
		}

		void inorder(){
			inoderAuxilery(root);
		}
//		int inorder(PieceOnBoard board[]){
//					return inoderAuxilery(root, board);
//				}
		void inoderAuxilery(Vertex* v){
			if(v!=NULL){
				inoderAuxilery(v->left);
				inoderAuxilery(v->right);
			}
			return;
		}
	Vertex* findVertex(Tower* tower){
		int diff;
		Vertex* currVertex=root ;
					while(currVertex){
						diff=compare(currVertex->data, tower);
						if(diff==0)return currVertex;
						if(diff<0) currVertex=currVertex->right;
						else currVertex=currVertex->left;
						}
					return NULL;
	}

	void deleteVertex(Tower* tower){
		Vertex* currVertex=root ;
		int diff;
		Vertex* dest=NULL;
		while(currVertex!=NULL){
			diff=compare(currVertex->data, tower);
			if(diff==0){
				dest=currVertex;
				break;
			}
			if(diff<0) currVertex=currVertex->right;
			else currVertex=currVertex->left;
		}
		if(dest==NULL) return;
		Vertex* fixFrom;
		if(dest->right==NULL && dest->left==NULL){
			fixFrom = dest->parent;
			deleteLeaf(*dest);
		}
		else if(!(dest->right!=NULL && dest->left!=NULL)){
			fixFrom=dest;
			deleteParentToOne(*dest);
		}
		else{
			Vertex* next=findNext(dest);
			dest->data=next->data;
			if(next->right==NULL){
				fixFrom = next->parent;
				deleteLeaf(*next);
			}
			else{
				fixFrom=next;
				deleteParentToOne(*next);
			}
		}
		fixBfRemove(fixFrom);
	}

	int smallerThen(int position, int height){
		int result=0;
		CompareOneTower comp(height,position);
		Vertex* v=root;
		while(v!=NULL){
			if(comp(v->data)>0)v=v->left;
			else{
				if(v->left!=NULL) result=result+v->left->children+1;
				else result++;
				v=v->right;
			}
		}
		return result;
	}

	int biggerThen(int position, int height){
		int result=0;
		CompareOneTower comp(height,position);
		Vertex* v=root;
		while(v!=NULL){
			if(comp(v->data)<0)v=v->right;
			else{
				if(v->right!=NULL) result=result+v->right->children+1;
				else result++;
				v=v->left;
			}
		}
		return result;
	}
//**************************************draw the tree***************************************************
		      /**       * dump the map into dotty format
		            */
		            void dumpMap_(const std::string& sName) {
		                std::ofstream ofs(sName.c_str());
		                ofs << "digraph X { " << std::endl;
		                drawNode_(ofs, root);
		                ofs << "}" << std::endl;
		            }

		            /**		            * create a node string representation
		            */
		            void createNode(Vertex* pCurr, std::ostream& ssOut) {
		                ssOut << "\"R.C: [" << pCurr->data->_root->_tower <<","<< pCurr->data->_size<< "], chil':  " << pCurr->children << "\"";
		            }

		            /**
		            * draw a single node for dotty output
		            */
		            void drawNode_(std::ofstream& fsOut, Vertex* pCurr) {
		                if (!pCurr) {
		                    return;
		                }
		                std::stringstream ssNode1, ssNode2, ssNode3, ssNodeTmp, ssNodeTmp2;
	                createNode(pCurr, ssNode1);
	                if (pCurr->left) {
		                    createNode(pCurr->left, ssNode2);
		                    createNode(pCurr->left->parent, ssNodeTmp);
		                    fsOut << ssNode1.str() << " -> " << ssNode2.str() << " [label=\"L\"];" << std::endl;
		                    fsOut << ssNode2.str() << " -> " << ssNodeTmp.str() << " [label=\"PL\"];" << std::endl;
		                }
		                if (pCurr->right) {
		                    createNode(pCurr->right,ssNode3);
		                    createNode(pCurr->right->parent, ssNodeTmp2);
		                    fsOut << ssNode1.str() << " -> " << ssNode3.str() << " [label=\"R\"];" << std::endl;
		                    fsOut << ssNode3.str() << " -> " << ssNodeTmp2.str() << " [label=\"PR\"];" << std::endl;
		                }
		                if (pCurr->left) {
		                    drawNode_(fsOut, pCurr->left);
		                }
		                if (pCurr->right) {
		                    drawNode_(fsOut, pCurr->right);
		                }
		                return;
		            }
};
class Lego2 : public Lego{
	AVL_Tree<compareTowers> _towersTree;
    int _singletones;
public:
	Lego2():_towersTree(), _singletones(0){}
	virtual ~Lego2(){
	}

	StatusType addCube(int length, int width){
		if(length<1 || width<1) return INVALID_INPUT;
		Cube temp = {width, length, -1, -1, -1, 0};
		Cube* newCube=new Cube;
		*newCube= temp;
		Tower* newTower=new Tower(newCube);
		newCube->_tower=_towers.insert(newTower);
		newCube->_position = _pieces.insert(newCube);
		_towersTree.addVertex(newTower);
		_singletones++;
		return SUCCESS;

	}
	StatusType putOnTop(int cubeUp,int cubeDown){
		if(cubeUp<0 || cubeDown<0){
			return INVALID_INPUT;
		}
		int towerUp = find(cubeUp,NULL);
		int towerDown = find(cubeDown,NULL);
		if(towerUp==-1 || towerDown==-1 || towerDown==towerUp){
			return FAILURE;
		}
		int downLength = _towers[towerDown]->_top->_length;
		int downWidth = _towers[towerDown]->_top->_width;
		int upWidth = _towers[towerUp]->_base->_width;
		int upLength = _towers[towerUp]->_base->_length;
		if( ! ((upLength<= downWidth && upWidth<=downLength)
				||((upLength<=downLength && upWidth<=downWidth))) ){
			return FAILURE;
		}
		int toDeleteTower;
		if(_towers[towerDown]->_size!=1){
				_towersTree.deleteVertex(_towers[towerDown]);
			}
			else _singletones--;
			if(_towers[towerUp]->_size!=1){
				_towersTree.deleteVertex(_towers[towerUp]);
			}
			else _singletones--;
			_towersTree.deleteVertex(_towers[towerDown]);
			_towersTree.deleteVertex(_towers[towerUp]);
		if(_towers[towerDown]->_size < _towers[towerUp]->_size){
			_towers[towerUp]->_root->_relativeHight += _towers[towerDown]->_size;
			_towers[towerDown]->_root->_relativeHight -= _towers[towerUp]->_root->_relativeHight;
			_towers[towerDown]->_root->_parent=_towers[towerUp]->_root->_position;
			_towers[towerUp]->_size += _towers[towerDown]->_size;
			_towers[towerUp]->_base = _towers[towerDown]->_base;
			_towers[towerDown]->_root->_tower=-1;
			toDeleteTower = towerDown;
			_towersTree.addVertex(_towers[towerUp]);
		}else{
			_towers[towerUp]->_root->_relativeHight += _towers[towerDown]->_size;
			_towers[towerUp]->_root->_relativeHight -= _towers[towerDown]->_root->_relativeHight;
			_towers[towerUp]->_root->_parent=_towers[towerDown]->_root->_position;
			_towers[towerDown]->_size += _towers[towerUp]->_size;
			_towers[towerDown]->_top = _towers[towerUp]->_top;
			_towers[towerUp]->_root->_tower=-1;
			toDeleteTower = towerUp;
			_towersTree.addVertex(_towers[towerDown]);
		}
		delete _towers[toDeleteTower];
		_towers.current--;
		if(toDeleteTower==_towers.current){
			_towers.edit(_towers.current,NULL);
			return	SUCCESS;
		}
		if(_towers[_towers.current]->_size!=1) _towersTree.deleteVertex(_towers[_towers.current]);
		_towers.edit(toDeleteTower,_towers[_towers.current]);
		_towers[toDeleteTower]->_root->_tower=toDeleteTower;
		if(_towers[toDeleteTower]->_size!=1) _towersTree.addVertex(_towers[toDeleteTower]);
		_towers.edit(_towers.current,NULL);
		return SUCCESS;
	}

	StatusType TowersOfHeightBetween(int min, int max, int* num){
		if(min<0 ||  max<0 || min>max || num==NULL) return INVALID_INPUT;
		int result=_towers.current;
		result-=_towersTree.biggerThen(_towers.current,max);
		result-=_towersTree.smallerThen(-1,min);
		*num=result;
		if(min>1 || max<1) *num-=_singletones;
		return SUCCESS;
	}



};


//int main(){
//	Lego lego;
//	int h1,h2;
//	lego.addCube(4,5);
//	std::cout<<lego._pieces.current<<" "<<lego._towers.current; // 1 1
//	lego.addCube(7,7);
//	lego.addCube(6,8);
//	std::cout<<std::endl<<lego._pieces.current<<" "<<lego._towers.current; // 3 3
//	std::cout<<std::endl<<lego._pieces[0]->_length<<" "<<lego._pieces[0]->_width <<
//			" "<<lego._pieces[0]->_parent; //4 5 -1
//	std::cout<<std::endl<<lego._pieces[1]->_length<<" "<<lego._pieces[1]->_width <<
//				" "<<lego._pieces[1]->_relativeHight; //7 7 0
//	std::cout<<std::endl<<lego._pieces[2]->_length<<" "<<lego._pieces[2]->_width <<
//				" "<<lego._pieces[2]->_relativeHight; //6 8 0
//	std::cout<<std::endl<<lego._pieces[2]->_tower<<" == 2"<<std::endl;
//	std::cout<<std::endl<<lego._pieces[0]->_tower<<" == 0";
//
//	lego.addCube(2,3);
//	lego.addCube(3,2);
//	lego.addCube(9,6);
//	std::cout<<std::endl<<lego.putOnTop(1,7); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(-1,7); //-3  wrong input
//	std::cout<<std::endl<<lego.putOnTop(0,-7); //-3  wrong input
//	std::cout<<std::endl<<lego.putOnTop(0,0); //-1   same tower
//	std::cout<<std::endl<<lego.putOnTop(2,2); //-1   same tower
//	std::cout<<std::endl<<lego.putOnTop(1,2);//-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(2,1); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(5,1); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(4,3); //0    success
//	std::cout<<std::endl<<lego._towers.current; //5
//	std::cout<<std::endl<<lego.find(4,NULL)<<" == "<<lego.find(3,NULL); // 3 == 3
//	std::cout<<std::endl<<lego._towers[3]->_size; //2
//	std::cout<<std::endl<<lego.putOnTop(0,3); //-1
//	std::cout<<std::endl<<lego.find(5,NULL); //4
//	lego.addCube(2,2);
//	std::cout<<std::endl<<lego.find(6,NULL); //5
//	std::cout<<std::endl<<lego._towers.current; //6
//	std::cout<<std::endl<<lego.putOnTop(6,3);//0
//	std::cout<<std::endl<<lego.find(4,NULL)<<" == "<<lego.find(3,NULL)<<" == "<<lego.find(6,NULL); // 3 == 3 == 3
//	std::cout<<std::endl<<" top tower 3 size: "<<lego._towers[3]->_top->_length<<" , "<<lego._towers[3]->_top->_width;// 2 , 2
//	std::cout<<std::endl<<lego._towers[3]->_size; //3
//	std::cout<<std::endl<<lego._towers.current; //5
//	std::cout<<std::endl<<lego._towers[4]->_base->_position;//5
//	std::cout<<std::endl<<lego.putOnTop(0,1);//0
//	std::cout<<std::endl<<lego._towers.current; //4
//	std::cout<<std::endl<<lego._towers[0]->_base->_position;//5
//	std::cout<<std::endl<<lego.putOnTop(0,6); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(0,3); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(1,4); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(1,6); //-1  wrong dimensions
//	std::cout<<std::endl<<lego.putOnTop(4,6); //-1  same tower
//	std::cout<<std::endl<<lego.putOnTop(6,0); //0 success
//	std::cout<<std::endl<<lego.putOnTop(6,0); //-1  same tower
//	std::cout<<std::endl<<lego._towers.current; //3
//	std::cout<<std::endl<<lego.find(4,NULL);//1
//	std::cout<<std::endl<<lego.find(5,NULL);//0
//	std::cout<<std::endl<<lego.find(2,NULL);//2
//	lego.towerHeight(1,&h1);lego.towerHeight(6,&h2);
//	std::cout<<std::endl<<lego._towers[1]->_size<<" == "<<h1<<" == "<<h2; //5 == 5 == 5
//	lego.find(6,&h1); lego.find(4,&h2); std::cout<<std::endl<<h1<<" "<<h2<<" "; // 4 3 2 1 0
//	lego.find(3,&h1); lego.find(0,&h2); std::cout<<h1<<" "<<h2<<" ";
//	lego.find(1,&h1); std::cout<<h1<<" ";
//
//
//	return 0;
//}

